package com.epfresh.api.http;

import android.support.annotation.NonNull;
import android.util.Log;

import com.epfresh.api.constant.Constant;
import com.epfresh.api.entity.ResponseEntity;
import com.epfresh.api.entity.ResponseError;
import com.epfresh.api.http.volley.AuthFailureError;
import com.epfresh.api.http.volley.NetworkResponse;
import com.epfresh.api.http.volley.Request;
import com.epfresh.api.http.volley.Response;
import com.epfresh.api.http.volley.RetryPolicy;
import com.epfresh.api.http.volley.VolleyError;
import com.epfresh.api.http.volley.toolbox.HttpHeaderParser;
import com.epfresh.api.utils.L;
import com.google.gson.Gson;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by wzh on 2016/3/15.
 */
public class HttpRequest<T> extends Request<ResponseEntity<T>> {
    //没有网络
    public static final int FAIL_NO_NET = 1111;
    //网络故障
    public static final int FAIL_NET_FAULT = 1112;

    //资源未找到404
    public static final int FAIL_NOT_FOUND = 2221;
    //数据错误
    public static final int FAIL_DATA_FAULT = 2222;
    //数据编码错误
    public static final int FAIL_DATA_ENCODE = 3331;
    //数据编码解析为null
    public static final int FAIL_DATA_ENCODE_NULL = 3332;
    //返回数据为空
    public static final int FAIL_DATA_EMPTY = 3333;
    //Json解析错误
    public static final int FAIL_JSON_PARSER = 3334;
    public static final int FAIL_JSON_NULL = 3335;
//    public static final int FAIL_JSON_NULL = 3335;

    private String Tag = "HttpRequest";
    private Map<String, String> headers;
    private Object data;
    private OnRequestListener<T> onRequestListener;

    public HttpRequest(Object data, OnRequestListener<T> onRequestListener) {
        super(Method.POST, Constant.URL_BASE, null);
        this.data = data;
        this.headers = null;
        this.onRequestListener = onRequestListener;
    }
    public HttpRequest(Object data,String baseUrl, OnRequestListener<T> onRequestListener) {
        super(Method.POST, baseUrl, null);
        this.data = data;
        this.headers = null;
        this.onRequestListener = onRequestListener;
    }
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        if (headers == null) {
            headers = new HashMap<>();
        }
        headers.put("Accept", "application/json");
       // headers.put("Content-Type", "application/json; charset=UTF-8");
        return headers;
    }

    @Override
    public String getBodyContentType() {
        return "application/json; charset=UTF-8";
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        if (data != null) {
            try {
                String jsonStr = data.toString();
//                Log.e(Tag, "URL_BASE:" + getOriginUrl());
                L.e(Tag, "request:" + jsonStr);
                if (jsonStr != null) {
                    return jsonStr.getBytes("utf-8");
                } else {
                    //{@link RequestEntity} json to string error

                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return super.getBody();
    }

    // UI线程执行
    @Override
    protected void deliverResponse(ResponseEntity<T> response) {
        if (response != null) {
            ResponseError error = response.getError();
            if (error != null) {
                int errorCode = error.getErrorCode();
                String errorMsg = error.getErrorInfo();
                if (errorMsg == null || "".equals(errorMsg)) {
                    errorMsg = "No errorMsg";
                }
                int errorType = error.getErrorType();
                if (errorType > 0) {//非服务器response字段中返回错误
                    if (errorCode == HttpURLConnection.HTTP_NOT_FOUND || errorCode == FAIL_NOT_FOUND) {//404
                        onFail(FAIL_NOT_FOUND, "404", getTag());
                    } else if (errorCode == FAIL_DATA_EMPTY) {
                        onFail(FAIL_DATA_EMPTY, "data empty", getTag());
                    } else if (errorCode == FAIL_DATA_ENCODE_NULL) {
                        onFail(FAIL_DATA_ENCODE_NULL, "data encode null", getTag());
                    } else if (errorCode == FAIL_DATA_ENCODE) {
                        onFail(FAIL_DATA_ENCODE, "data encode", getTag());
                    } else {
                        onFail(errorCode, errorMsg, getTag());
                    }
                } else {
                    onRequestListener.onResponseError(errorCode, errorMsg, getTag());
                }

            } else {
                //没有错误
                NetworkResponse networkResponse = response.getNetworkResponse();
                if (networkResponse.statusCode == HttpURLConnection.HTTP_NOT_FOUND) {
                    onFail(FAIL_NOT_FOUND, "404", getTag());
                } else {
                    T responseElement = response.getResponseElement();
                    if (responseElement == null) {
                        onFail(FAIL_JSON_PARSER, "gson to obj back null", getTag());
                    } else {
                        onResponse(response, getTag());
                    }

                }


            }
        } else {
            onFail(FAIL_JSON_PARSER, "gson to response obj back null", getTag());
        }

    }

    @Override
    public void deliverError(VolleyError error) {
        String message = error.getMessage();
        NetworkResponse networkResponse = error.networkResponse;
        if (networkResponse != null) {
            int statusCode = networkResponse.statusCode;
            if (statusCode == HttpURLConnection.HTTP_NOT_FOUND) {
                onFail(FAIL_NOT_FOUND, message, getTag());
            } else {
                long networkTimeMs = networkResponse.networkTimeMs;
                RetryPolicy retryPolicy = getRetryPolicy();
                int currentTimeout = retryPolicy.getCurrentTimeout();
                int currentRetryCount = retryPolicy.getCurrentRetryCount();
                if (networkTimeMs > currentRetryCount * currentTimeout) {
                    //超时
                    onFail(FAIL_NET_FAULT, message, getTag());
                } else {

                    onFail(FAIL_NET_FAULT, message, getTag());
                }
            }

        } else {
            onFail(FAIL_NET_FAULT, message, getTag());
        }

    }

    // 子线程执行
    @Override
    protected Response<ResponseEntity<T>> parseNetworkResponse(NetworkResponse response) {
        byte[] data = response.data;

        if (data == null) {
            ResponseEntity<T> result = createResponseEntity(response, FAIL_DATA_EMPTY, "data_empty", 1);
            return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));

        }
        try {
            String parsed = new String(data, "utf8");

            if (parsed != null) {
                //L.e(Tag, "response:" + parsed);
//                Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
                Gson gson = new Gson();
                ResponseEntity<T> result = gson.fromJson(parsed, ResponseEntity.class);
//                L.e(Tag, "ResponseEntity:" + result);
                if (result != null) {
                    result.setResponse(getResponseStr(parsed));
                    result.setResponseStr(parsed);
                    result.setNetworkResponse(response);
                    String responseStr = result.getResponse();

                    //判断返回response字段是否有误
                    if (responseStr != null && !"".equals(responseStr)) {
                        //返回Json对象
                        T t = jsonToObj(responseStr);
                        result.setResponseElement(t);
                        L.e(Tag, "t:" + t);
                    } else {
                        //response，为空
//                        result = createResponseEntity(response, FAIL_JSON_NULL, "json_null");
//                        return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));
                    }

                } else {
                    //result， gson解析失败
                }
                return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));
            } else {
                ResponseEntity<T> result = createResponseEntity(response, FAIL_DATA_ENCODE_NULL, "data_encode", 1);
                return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            ResponseEntity<T> result = createResponseEntity(response, FAIL_DATA_ENCODE, "data_encode", 1);
            return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));
        }
    }

    private String getResponseStr(String parsed) {
        try {
            JSONObject jo = new JSONObject(parsed);
            if (jo.has("response")) {
                return jo.getString("response");
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;

    }

    @NonNull
    private ResponseEntity<T> createResponseEntity(NetworkResponse response, int failCode, String msg, int errorType) {
        ResponseEntity<T> result = new ResponseEntity<>();
        ResponseError error = new ResponseError();
        error.setErrorCode(failCode);
        error.setErrorInfo(msg);
        error.setErrorType(errorType);
        result.setError(error);
        result.setNetworkResponse(response);
        return result;
    }

    //返回json数据中的response字段，在子线程中执行
    public T jsonToObj(String jsonStr) {
//        L.i("response", "responseStr=" + jsonStr);
        return onRequestListener.jsonToObj(jsonStr);
    }


    //返回失败，在UI线程执行
    public void onFail(int failCode, Object arg, Object tag) {
        L.e("response", "failCode=" + failCode + "--arg=" + arg + "--tag=" + tag);
        onRequestListener.onFail(failCode, arg, tag);
    }

    //在UI线程执行
    public void onStart(Object tag) {
//        L.e("response", "onstart");
        onRequestListener.onStart(tag);
    }

    //在UI线程执行
    public void onResponse(ResponseEntity<T> response, Object tag) {
        L.e("response", "response=" + response + "--tag=" + tag);
        onRequestListener.onResponse(response, tag);
    }


}

